﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using WooCoo.Tools;

namespace WooCoo.DataPortal.WebHost.ODataServer
{
    public static class HttpRequestMessageExtensions
    {
        private const string PreferHeaderName = "Prefer";
        private const string PreferenceAppliedHeaderName = "Preference-Applied";
        private const string ReturnContentHeaderValue = "return-content";
        private const string ReturnNoContentHeaderValue = "return-no-content";
        public static HttpResponseMessage CreateSingleEntityResponseFromRuntimeType(this HttpRequestMessage request, IEnumerable enumerable)
        {
            IEnumerator enumerator = enumerable.GetEnumerator();
            if (!enumerator.MoveNext())
            {
                return request.CreateResponse(HttpStatusCode.NotFound);
            }
            object entity = enumerator.Current;
            return request.CreateEntityResponse(HttpStatusCode.OK, entity);
        }

        public static HttpResponseMessage CreateSingleEntityResponse<TEntity>(this HttpRequestMessage request, TEntity entity) where TEntity : class
        {
            if (entity == null)
            {
                return request.CreateResponse(HttpStatusCode.NotFound);
            }
            else
            {
                return request.CreateResponse(HttpStatusCode.OK, entity);
            }
        }

        public static HttpResponseMessage CreateEntityResponse<T>(this HttpRequestMessage request, HttpStatusCode statusCode, T value)
        {
            return CreateEntityResponse<T>(request, statusCode, value, null);
        }
        public static HttpResponseMessage CreateEntityResponse<T>(this HttpRequestMessage request, HttpStatusCode statusCode, T value, HttpConfiguration configuration)
        {
            if (request == null)
            {
                throw Error.ArgumentNull("request");
            }
            configuration = (configuration ?? request.GetConfiguration());
            if (configuration == null)
            {
                throw Error.InvalidOperation("HttpRequestMessageExtensions_NoConfiguration");
            }
            IContentNegotiator contentNegotiator = configuration.Services.GetContentNegotiator();
            if (contentNegotiator == null)
            {
                throw Error.InvalidOperation("HttpRequestMessageExtensions_NoContentNegotiator");
            }
            IEnumerable<MediaTypeFormatter> formatters = configuration.Formatters;
            ContentNegotiationResult contentNegotiationResult = contentNegotiator.Negotiate(value.GetType(), request, formatters);
            HttpResponseMessage httpResponseMessage = new HttpResponseMessage();
            try
            {
                if (contentNegotiationResult == null)
                {
                    httpResponseMessage.StatusCode = HttpStatusCode.NotAcceptable;
                }
                else
                {
                    httpResponseMessage.StatusCode = statusCode;
                    httpResponseMessage.Content = new ObjectContent(value.GetType(), value, contentNegotiationResult.Formatter, contentNegotiationResult.MediaType);
                }
                httpResponseMessage.RequestMessage = request;
            }
            catch
            {
                httpResponseMessage.Dispose();
                throw;
            }
            return httpResponseMessage;
        }

        private static JsonMediaTypeFormatter jf = CreateJsonFormatter();
        private static MediaTypeHeaderValue jsonMedia = new MediaTypeHeaderValue("application/json");
        public static HttpResponseMessage CreateJsonResponse<T>(this HttpRequestMessage request, HttpStatusCode statusCode, T value)
        {
            HttpResponseMessage httpResponseMessage = new HttpResponseMessage();
            try
            {
                MediaTypeFormatter formatter = jf;
                httpResponseMessage.StatusCode = statusCode;
                httpResponseMessage.Content = new ObjectContent(value.GetType(), value, formatter, jsonMedia);
                httpResponseMessage.RequestMessage = request;
            }
            catch
            {
                httpResponseMessage.Dispose();
                throw;
            }
            return httpResponseMessage;
        }

        private static JsonMediaTypeFormatter CreateJsonFormatter()
        {
            var jf = new JsonMediaTypeFormatter() { UseDataContractJsonSerializer = false };
            jf.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
            return jf;
        }
    }
}
